#ifndef _SHARP_RNG_H
#define _SHARP_RNG_H

#include "sharp-common.h"

#ifndef SHARP_RNG_STATES
#define SHARP_RNG_STATES 16
#endif /* SHARP_RNG_STATE_NUM */

#ifndef SHARP_RNG_RANDFILE
#define SHARP_RNG_RANDFILE "/dev/urandom"
#endif /* SHARP_RNG_RANDFILE */

/**
 * @file src/rng.c
 */

typedef struct sharp_rng_s sharp_rng;

/**
 * Describes an RNG.
 * Works mostly like a Mersenne Twister
 */
struct sharp_rng_s {
    /** contains 16 random numbers */
    int state[SHARP_RNG_STATES];
    /** state/random number we're on currently */
    int idx;
};

/**
 * Initialize the random number generator.
 *
 * This initializes just one, the internal, RNG. If you need to use multiple
 * RNGs, refer to sharp_rng_init_r().
 */
void sharp_rng_init(void);

/**
 * Initialize a random number generator.
 * @param rng the RNG in question
 *
 * If you call this function because you need to use multiple different RNGs,
 * make sure you always use the reentrant variants of the RNG functions.
 */
void sharp_rng_init_r(sharp_rng *rng);

/**
 * Gets a random integer from the internal RNG.
 */
int sharp_rng_get_int(void);

/**
 * Gets a random integer from an RNG.
 * @param rng the RNG to use
 */
int sharp_rng_get_int_r(sharp_rng *rng);

/**
 * Get an unsigned integer within a certain range from the internal RNG.
 * @param min the lowest possible number
 * @param max the highest possible number
 */
int sharp_rng_get_range(int min, int max);

/**
 * Get an unsigned integer within a certain range from an RNG.
 * @param rng the RNG to use
 * @param min the lowest possible number
 * @param max the highest possible number
 */
int sharp_rng_get_range_r(sharp_rng *rng, int min, int max);

/**
 * Get a float from the internal RNG.
 */
float sharp_rng_get_float(void);

/**
 * Get a float from an RNG.
 * @param rng the RNG to use
 *
 * The float will always be in the range of 0 <= float <= 1.
 */
float sharp_rng_get_float_r(sharp_rng *rng);

/**
 * Get an ASCII string from the RNG.
 * @param dest pointer to the target string
 * @param size number of characters to store. The final \0 will not be written!
 */
void sharp_rng_get_string(char *dest, int size);

/**
 * Get an ASCII string from an RNG.
 * @param rng the RNG to use
 * @param dest pointer to the target string
 * @param size number of characters to store. The final \0 will not be written!
 */
void sharp_rng_get_string_r(sharp_rng *rng, char *dest, int size);

#endif /* _SHARP_RNG_H */
